﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode]
public class DoActionDelay : MonoBehaviour {
    
	private static DoActionDelay m_Instance;
	static DoActionDelay instance
	{
		get
		{
			if (m_Instance == null)
			{
				m_Instance = new UnityEngine.GameObject("DelayAction").AddComponent<DoActionDelay>();
				DontDestroyOnLoad(m_Instance.gameObject);
			}
			return m_Instance;
		}
	}

	struct DelayActionStruct
	{
		public float beginTime;
		public float duration;
		public Action action;
	}
	private List<DelayActionStruct> m_DelayActions = new List<DelayActionStruct>();
	
	    
	public static void DelayAction(float time,Action _action)
	{
		//GameDebug.Log($"DelayAction:{time}");
		DoActionDelay.instance.DelayDoAction(time,_action);
	}

	public void DelayDoAction(float time,Action _action)
	{
		//GameDebug.Log($"准备执行：{Time.realtimeSinceStartup}  延迟时间:{time}  ");

		DelayActionStruct newAction = new DelayActionStruct
		{
			beginTime = Time.realtimeSinceStartup,
			duration = time,
			action = ()=>
			{
				//GameDebug.Log($"时间到 执行：{Time.realtimeSinceStartup}  ");
				try
				{
					_action?.Invoke();
				}
				catch (Exception e)
				{
					GameDebug.LogError(e);
				}
			}
		};
		m_DelayActions.Add(newAction);
	}

	void CheckDelayAction()
	{
		if (m_DelayActions == null)
		{
			m_DelayActions = new List<DelayActionStruct>();
		}
		
		if(m_DelayActions.Count > 0)
		{
			for (int i = 0; i < m_DelayActions.Count; )
			{
				if (Time.realtimeSinceStartup - m_DelayActions[i].beginTime >= m_DelayActions[i].duration)
				{
					m_DelayActions[i].action?.Invoke();
					m_DelayActions.RemoveAt(i);
				}
				else
				{
					i++;
				}
			}
		}
		
	}

#if DEBUG
	private int testSeq;
	public float testTime = 5;
	[ContextMenu("Test")]
	void Test()
	{
		int cur = testSeq++;
		GameDebug.Log($"准备执行：{Time.realtimeSinceStartup}  延迟时间:{testTime}  testSeq:{cur}");
		DelayDoAction(testTime, () =>
		{
			GameDebug.Log($"时间到 执行：{Time.realtimeSinceStartup}  testSeq:{cur}");
		});
	}
#endif

	
	// Update is called once per frame
	void Update ()
	{
		 CheckDelayAction();

	}
}
